<?php
/**
 * Created by PhpStorm.
 * User: l-eru
 * Date: 18-4-25
 * Time: 上午11:04
 */

namespace Aliyun;

//access_key_id LTAI8uPRHG5ahEtg
//access_key_secret o4TcXAr3e0o5fYUc65SwTx2do3SSP1
//template_id SMS_130924984

use Aliyun\Api\Sms\Request\V20170525\QuerySendDetailsRequest;
use Aliyun\Api\Sms\Request\V20170525\SendBatchSmsRequest;
use Aliyun\Api\Sms\Request\V20170525\SendSmsRequest;
use Aliyun\Core\Config;
use Aliyun\Core\DefaultAcsClient;
use Aliyun\Core\Profile\DefaultProfile;

class AliSms
{
    protected static $instance = null;

    protected $acsClient;

    protected $protocol;

    protected $signName;

    private function __construct()
    {
        Config::load();

        $this->acsClient = $this->getAcsClient();

        $this->protocol = config('sms.protocol');

        $this->signName = config('sms.sign_name');
    }

    public static function getInstance()
    {
        if (empty(self::$instance)) {
            self::$instance = new static();
        }

        return self::$instance;
    }

    /**
     * 取得AcsClient
     *
     * @return DefaultAcsClient
     */
    protected function getAcsClient() {
        //产品名称:云通信流量服务API产品,开发者无需替换
        $product = "Dysmsapi";

        //产品域名,开发者无需替换
        $domain = "dysmsapi.aliyuncs.com";

        $accessKeyId = config('sms.access_key_id'); // AccessKeyId

        $accessKeySecret = config('sms.access_key_secret'); // AccessKeySecret

        // 暂时不支持多Region
        $region = "cn-hangzhou";

        // 服务结点
        $endPointName = "cn-hangzhou";


        //初始化acsClient,暂不支持region化
        $profile = DefaultProfile::getProfile($region, $accessKeyId, $accessKeySecret);

        // 增加服务结点
        DefaultProfile::addEndpoint($endPointName, $region, $product, $domain);

        // 初始化AcsClient用于发起请求
        return new DefaultAcsClient($profile);
    }

    /**
     * 发送短信
     *
     * @param string $phoneNumber 短信接收号码
     * @param string $templateId 模板ID
     * @param array $templateParam 模板变量
     * @param string $signName 阿里大于短信签名名称
     * @return mixed|\SimpleXMLElement
     */
    public function send(string $phoneNumber, string $templateId, array $templateParam, string $signName = '')
    {
        // 初始化SendSmsRequest实例用于设置发送短信的参数
        $request = new SendSmsRequest();

        //可选-启用https协议
        $request->setProtocol($this->protocol);

        // 必填，设置短信接收号码
        $request->setPhoneNumbers($phoneNumber);

        // 必填，设置签名名称，应严格按"签名名称"填写，请参考: https://dysms.console.aliyun.com/dysms.htm#/develop/sign
        $request->setSignName($signName ?: $this->signName);

        // 必填，设置模板CODE，应严格按"模板CODE"填写, 请参考: https://dysms.console.aliyun.com/dysms.htm#/develop/template
        $request->setTemplateCode($templateId);

        // 可选，设置模板参数, 假如模板中存在变量需要替换则为必填项
        $request->setTemplateParam(json_encode($templateParam, JSON_UNESCAPED_UNICODE));

        // 可选，设置流水号
        //$request->setOutId("yourOutId");

        // 选填，上行短信扩展码（扩展码字段控制在7位或以下，无特殊需求用户请忽略此字段）
        //$request->setSmsUpExtendCode("1234567");

        // 发起访问请求
        $acsResponse = $this->acsClient->getAcsResponse($request);

        return $acsResponse;
    }


    /**
     * 批量发送短信
     *
     * @param array $phoneNumbers 要发送的短信号码数组
     * @param string $templateId 模板ID
     * @param array $templateParams 模板变量
     * @param array $signNames 短信签名，与短信号码长度匹配
     * @return mixed|\SimpleXMLElement
     */
    public function sendBatch(array $phoneNumbers, string $templateId, array $templateParams, array $signNames = []) {

        // 初始化SendSmsRequest实例用于设置发送短信的参数
        $request = new SendBatchSmsRequest();

        //可选-启用https协议
        $request->setProtocol($this->protocol);

        // 必填:待发送手机号。支持JSON格式的批量调用，批量上限为100个手机号码,批量调用相对于单条调用及时性稍有延迟,验证码类型的短信推荐使用单条调用的方式
        $request->setPhoneNumberJson(json_encode($phoneNumbers, JSON_UNESCAPED_UNICODE));

        // 如果签名为空，则默认读取配置中的签名
        if (empty($signNames)) {
            for ($i = 0; $i < count($phoneNumbers); ++$i) {
                $signNames[] = $this->signName;
            }
        }
        // 必填:短信签名-支持不同的号码发送不同的短信签名
        $request->setSignNameJson(json_encode($signNames, JSON_UNESCAPED_UNICODE));

        // 必填:短信模板-可在短信控制台中找到
        $request->setTemplateCode($templateId);

        // 必填:模板中的变量替换JSON串,如模板内容为"亲爱的${name},您的验证码为${code}"时,此处的值为
        // 友情提示:如果JSON中需要带换行符,请参照标准的JSON协议对换行符的要求,比如短信内容中包含\r\n的情况在JSON中需要表示成\\r\\n,否则会导致JSON在服务端解析失败
        $request->setTemplateParamJson(json_encode($templateParams, JSON_UNESCAPED_UNICODE));

        // 可选-上行短信扩展码(扩展码字段控制在7位或以下，无特殊需求用户请忽略此字段)
        // $request->setSmsUpExtendCodeJson("[\"90997\",\"90998\"]");

        // 发起访问请求
        $acsResponse = $this->acsClient->getAcsResponse($request);

        return $acsResponse;
    }

    /**
     * 短信发送记录查询
     *
     * @param string $phoneNumber 要查询的手机号码
     * @param string $sendDate 发送日期，支持近30天以内查询, 格式为Ymd
     * @param int $curPage 查询当前页码, 默认为第一页
     * @param int $page 分页大小,  默认为10
     * @return mixed|\SimpleXMLElement
     */
    public function querySendDetails(string $phoneNumber, string $sendDate, int $curPage = 1, int $page = 10) {

        // 初始化QuerySendDetailsRequest实例用于设置短信查询的参数
        $request = new QuerySendDetailsRequest();

        //可选-启用https协议
        $request->setProtocol($this->protocol);

        // 必填，短信接收号码
        $request->setPhoneNumber($phoneNumber);

        // 必填，短信发送日期，格式Ymd，支持近30天记录查询
        $request->setSendDate($sendDate);

        // 必填，分页大小
        $request->setPageSize($page);

        // 必填，当前页码
        $request->setCurrentPage($curPage);

        // 选填，短信发送流水号
        // $request->setBizId("yourBizId");

        // 发起访问请求
        $acsResponse = $this->acsClient->getAcsResponse($request);

        return $acsResponse;
    }
}
